package org.magnerfuller.imtoolkit.server.connection.handler;

import org.magnerfuller.imtoolkit.server.naming.NamedModuleDirectory;
import org.magnerfuller.imtoolkit.server.service.ServiceDescription;

/**
 * 
 * Singleton Class ConnectionHandlerFactory
 * 
 * The singleton instance of this class creates ConnectionHandlers
 * from ConnectionHandlerDescriptions.
 * 
 * New ConnectionHandler class types are registered with this
 * factory so that instances of them can be created.
 *
 */
public class ConnectionHandlerFactory {

  /** me -- The singleton instance */
  private static ConnectionHandlerFactory me;
  
  /** directory -- The named-module directory that provides name lookup of modules. */
  private NamedModuleDirectory directory = new NamedModuleDirectory();
  
  /**
   * Get the singleton instance.
   * 
   * @return the singleton instance
   */
  public static ConnectionHandlerFactory getInstance() {
    if(me == null) {
      me = new ConnectionHandlerFactory();
    }
    return me;
  }//getInstance
  
  /**
   * Create a ConnectionHandler object based on a description of what
   * is to be created.
   * 
   * @param desc The description object for what is to be created.
   * @param serviceDesc The description for the service that is to be
   *        provided by the handler
   * @return the ConnectionHandler
   */
  public ConnectionHandler createConnectionHandler(ConnectionHandlerDescription desc,
      ServiceDescription serviceDesc) {
    
    ConnectionHandler handler;
    
    try {
      // Get the module name to use.
      String moduleName = desc.getHandlerData().get("medium");
      if(moduleName == null) {
        throw new Exception("ConnectionHandlerFactory::createConnectionHandler: No medium from description!");
      }
      
      // Look up the class to instantiate, based on the module name.
      Class module = directory.lookupModule(moduleName);
      if(module == null) {
        throw new Exception("ConnectionHandlerFactory::createConnectionHandler: No module " + 
            moduleName + " found!");
      }
      
      // Create the ConnectionHandler.
      handler = (ConnectionHandler)module.newInstance();
      handler.setServiceDescription(serviceDesc);
      handler.initialize(desc.getHandlerData());
      
    } catch(Exception e) {
      System.err.println(e);
      handler = null;
    }
    
    return handler;
  }//createConnectionHandler

  /**
   * Add a type of ConnectionHandler that is to be created
   * by this factory.
   * 
   * @param module the class of the ConnectionHandler one wants to be able to create
   */
  public void addHandlerModule(Class module) {
    directory.addModule(module);
  }//addHandlerModule
  
  /**
   * Add a type of ConnectionHandler that is to be created
   * by this factory.
   * 
   * @param module the class of the ConnectionHandler one wants to be able to create
   */
  public void addHandlerModule(Class module, String moduleName) {
    directory.addModule(module, moduleName);
  }//addHandlerModule
  
}//ConnectionHandlerFactory
